/*
 * TicketView.java
 *
 * Created on August 4, 2006, 3:42 PM
 */
package com.floreantpos.ui.views.order;

import com.floreantpos.POSConstants;
import com.floreantpos.PosException;
import com.floreantpos.main.Application;
import com.floreantpos.model.*;
import com.floreantpos.model.dao.MenuItemDAO;
import com.floreantpos.print.PosPrintService;
import com.floreantpos.ui.dialog.NumberSelectionDialog2;
import com.floreantpos.ui.dialog.POSMessageDialog;
import com.floreantpos.ui.views.SwitchboardView;
import com.floreantpos.ui.views.order.actions.OrderListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import javax.swing.JPanel;

/**
 *
 * @author MShahriar
 */
public class TicketView extends JPanel {

  private NumberFormat numberFormat = new DecimalFormat("#,##0.00", new DecimalFormatSymbols(new Locale("pt", "BR")));
  private java.util.Vector<OrderListener> orderListeners = new java.util.Vector<OrderListener>();
  private Ticket ticket;
  private String errorMessage = "Problemas com o Pedido:";

  public final static String VIEW_NAME = "TICKET_VIEW";

  public TicketView() {
    initComponents();

    ticketViewerTable.getRenderer().setInTicketScreen(true);
    ticketViewerTable.addMouseListener(new MouseAdapter() {

      @Override
      public void mouseClicked(MouseEvent e) {
        if (e.getButton() == 1 && e.getClickCount() == 2 && e.isControlDown()) {
          updateSelectionView();
          doShowUpdatedTime();
        } else if (e.getButton() == 1 && e.getClickCount() == 2) {
          updateSelectionView();
          doSetUnitPrice();
        }
      }

    });
  }

  private void initComponents() {
    java.awt.GridBagConstraints gridBagConstraints;

    jPanel1 = new com.floreantpos.swing.TransparentPanel();
    jSeparator1 = new javax.swing.JSeparator();
    jPanel3 = new com.floreantpos.swing.TransparentPanel();
    jLabel5 = new javax.swing.JLabel();
    jLabel6 = new javax.swing.JLabel();
    jLabel1 = new javax.swing.JLabel();
    jLabel2 = new javax.swing.JLabel();
    jSeparator2 = new javax.swing.JSeparator();
    jSeparator3 = new javax.swing.JSeparator();
    tfSubtotal = new javax.swing.JTextField();
    tfTax = new javax.swing.JTextField();
    tfDiscount = new javax.swing.JTextField();
    tfTotal = new javax.swing.JTextField();
    bottomPanel = new com.floreantpos.swing.TransparentPanel();
    btnPay = new com.floreantpos.swing.PosButton();
    btnCancel = new com.floreantpos.swing.PosButton();
    btnFinish = new com.floreantpos.swing.PosButton();
    jPanel5 = new com.floreantpos.swing.TransparentPanel();
    btnIncreaseAmount = new com.floreantpos.swing.PosButton();
    btnDecreaseAmount = new com.floreantpos.swing.PosButton();
    btnScrollUp = new com.floreantpos.swing.PosButton();
    btnScrollDown = new com.floreantpos.swing.PosButton();
    btnDelete = new com.floreantpos.swing.PosButton();
    jPanel2 = new com.floreantpos.swing.TransparentPanel();
    jScrollPane1 = new javax.swing.JScrollPane();
    ticketViewerTable = new com.floreantpos.ui.ticket.TicketViewerTable();

    setBorder(javax.swing.BorderFactory.createTitledBorder(null, com.floreantpos.POSConstants.TICKET, javax.swing.border.TitledBorder.CENTER, javax.swing.border.TitledBorder.DEFAULT_POSITION));
    setPreferredSize(new java.awt.Dimension(280, 463));
    setLayout(new java.awt.BorderLayout(5, 5));

    jPanel1.setLayout(new java.awt.BorderLayout(5, 5));
    jPanel1.add(jSeparator1, java.awt.BorderLayout.CENTER);

    jPanel3.setLayout(new java.awt.GridBagLayout());

    jLabel5.setFont(new java.awt.Font("Tahoma", 1, 12));
    jLabel5.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
    jLabel5.setText(com.floreantpos.POSConstants.SUBTOTAL + ":");
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 1;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.insets = new java.awt.Insets(3, 5, 0, 0);
    jPanel3.add(jLabel5, gridBagConstraints);

    jLabel6.setFont(new java.awt.Font("Tahoma", 1, 12));
    jLabel6.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
    jLabel6.setText(com.floreantpos.POSConstants.TOTAL + ":");
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 3;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.insets = new java.awt.Insets(0, 5, 3, 0);
    jPanel3.add(jLabel6, gridBagConstraints);

    jLabel1.setFont(new java.awt.Font("Tahoma", 1, 12));
    jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
    jLabel1.setText("Desc.:");
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 2;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 0);
    jPanel3.add(jLabel1, gridBagConstraints);

    jLabel2.setFont(new java.awt.Font("Tahoma", 1, 12));
    jLabel2.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
    jLabel2.setText("Grat.:");
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 2;
    gridBagConstraints.gridy = 2;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 0);
    jPanel3.add(jLabel2, gridBagConstraints);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 6;
    gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.weightx = 1.0;
    jPanel3.add(jSeparator2, gridBagConstraints);
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 0;
    gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.weightx = 1.0;
    jPanel3.add(jSeparator3, gridBagConstraints);

    tfSubtotal.setEditable(false);
    tfSubtotal.setFont(new java.awt.Font("Tahoma", 1, 12));
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.weightx = 1.0;
    gridBagConstraints.insets = new java.awt.Insets(3, 5, 0, 5);
    jPanel3.add(tfSubtotal, gridBagConstraints);

    tfTax.setEditable(false);
    tfTax.setFont(new java.awt.Font("Tahoma", 1, 12));
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.weightx = 1.0;
    gridBagConstraints.insets = new java.awt.Insets(3, 5, 0, 5);
    jPanel3.add(tfTax, gridBagConstraints);

    tfDiscount.setEditable(false);
    tfDiscount.setFont(new java.awt.Font("Tahoma", 1, 12));
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 1;
    gridBagConstraints.gridy = 2;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.weightx = 1.0;
    gridBagConstraints.insets = new java.awt.Insets(3, 5, 0, 5);
    jPanel3.add(tfDiscount, gridBagConstraints);

    tfTotal.setEditable(false);
    tfTotal.setFont(new java.awt.Font("Tahoma", 1, 12));
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 1;
    gridBagConstraints.gridy = 3;
    gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
    gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
    gridBagConstraints.weightx = 1.0;
    gridBagConstraints.insets = new java.awt.Insets(3, 5, 3, 5);
    jPanel3.add(tfTotal, gridBagConstraints);

    jPanel1.add(jPanel3, java.awt.BorderLayout.NORTH);

    bottomPanel.setLayout(new java.awt.GridBagLayout());

    btnPay.setText(com.floreantpos.POSConstants.PAY_NOW);
    btnPay.setPreferredSize(new java.awt.Dimension(76, 45));
    btnPay.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        doPayNow(evt);
      }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridwidth = 2;
    gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
    gridBagConstraints.weightx = 1.0;
    gridBagConstraints.insets = new java.awt.Insets(0, 0, 5, 0);
    bottomPanel.add(btnPay, gridBagConstraints);
    
    btnCancel.setText(com.floreantpos.POSConstants.CANCEL);
    btnCancel.setPreferredSize(new java.awt.Dimension(76, 45));
    btnCancel.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        doCancelOrder(evt);
      }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 1;
    gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
    gridBagConstraints.weightx = 1.0;
    bottomPanel.add(btnCancel, gridBagConstraints);

    btnFinish.setText(com.floreantpos.POSConstants.FINISH);
    btnFinish.setPreferredSize(new java.awt.Dimension(76, 45));
    btnFinish.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        doFinishOrder(evt);
      }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 1;
    gridBagConstraints.gridy = 1;
    gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
    gridBagConstraints.weightx = 1.0;
    gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 0);
    bottomPanel.add(btnFinish, gridBagConstraints);

    jPanel1.add(bottomPanel, java.awt.BorderLayout.SOUTH);

    jPanel5.setLayout(new java.awt.GridBagLayout());

    btnIncreaseAmount.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/add_user_32.png")));
    btnIncreaseAmount.setPreferredSize(new java.awt.Dimension(76, 45));
    btnIncreaseAmount.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        doIncreaseAmount(evt);
      }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
    gridBagConstraints.weightx = 1.0;
    jPanel5.add(btnIncreaseAmount, gridBagConstraints);

    btnDecreaseAmount.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/minus_32.png")));
    btnDecreaseAmount.setPreferredSize(new java.awt.Dimension(76, 45));
    btnDecreaseAmount.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        doDecreaseAmount(evt);
      }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
    gridBagConstraints.weightx = 1.0;
    gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 0);
    jPanel5.add(btnDecreaseAmount, gridBagConstraints);

    btnScrollUp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/up_32.png")));
    btnScrollUp.setPreferredSize(new java.awt.Dimension(76, 45));
    btnScrollUp.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        doScrollUp(evt);
      }
    });
    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
    gridBagConstraints.weightx = 1.0;
    gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 0);
    jPanel5.add(btnScrollUp, gridBagConstraints);

    btnScrollDown.setIcon(new javax.swing.ImageIcon(getClass().getResource("/images/down_32.png")));
    btnScrollDown.setPreferredSize(new java.awt.Dimension(76, 45));
    btnScrollDown.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        doScrollDown(evt);
      }
    });

    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 2;
    gridBagConstraints.gridy = 1;
    gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
    gridBagConstraints.weightx = 1.0;
    gridBagConstraints.insets = new java.awt.Insets(5, 5, 0, 0);
    jPanel5.add(btnScrollDown, gridBagConstraints);

    btnDelete.setText(com.floreantpos.POSConstants.DELETE);
    btnDelete.setPreferredSize(new java.awt.Dimension(80, 17));
    btnDelete.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        doDeleteSelection(evt);
      }
    });

    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.gridx = 0;
    gridBagConstraints.gridy = 1;
    gridBagConstraints.gridwidth = 2;
    gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
    gridBagConstraints.weightx = 1.0;
    gridBagConstraints.insets = new java.awt.Insets(5, 0, 0, 0);
    jPanel5.add(btnDelete, gridBagConstraints);

    jPanel1.add(jPanel5, java.awt.BorderLayout.CENTER);

    add(jPanel1, java.awt.BorderLayout.SOUTH);

    jPanel2.setLayout(new java.awt.BorderLayout());

    jScrollPane1.setBorder(null);
    jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
    jScrollPane1.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
    jScrollPane1.setPreferredSize(new java.awt.Dimension(180, 200));
    jScrollPane1.setViewportView(ticketViewerTable);

    jPanel2.add(jScrollPane1, java.awt.BorderLayout.CENTER);

    add(jPanel2, java.awt.BorderLayout.CENTER);
  }

  private void doFinishOrder(java.awt.event.ActionEvent evt) {
    try {
      updateModel();
      OrderController.saveOrder(ticket);

      ticket.clearDeletedItems();
      OrderController.saveOrder(ticket);

      if (isCheckMandatoryModifiers() && isTicketConstraintsOk()) {

        if (ticket.needsKitchenPrint()) {
          PosPrintService.printToKitchen(ticket);
        }

        OrderController.saveOrder(ticket);
        RootView.getInstance().showView(SwitchboardView.VIEW_NAME);

      } else {

        POSMessageDialog.showError(errorMessage);
        errorMessage = "Problemas com o Pedido:";

      }

    } catch (PosException x) {
      POSMessageDialog.showError(x.getMessage());
    } catch (Exception e) {
      POSMessageDialog.showError(Application.getPosWindow(), POSConstants.ERROR_MESSAGE, e);
    }
  }

  private void doCancelOrder(java.awt.event.ActionEvent evt) {
    if (ticket.getId() == null || (isCheckMandatoryModifiers() && isTicketConstraintsOk())) {
        RootView.getInstance().showView(SwitchboardView.VIEW_NAME);
    } else {
      POSMessageDialog.showError(errorMessage);
      errorMessage = "Problemas com o Pedido:";
    }
  }

  private void updateModel() {
    if (ticket.getTicketItems() == null || ticket.getTicketItems().isEmpty()) {
      throw new PosException(com.floreantpos.POSConstants.TICKET_IS_EMPTY_);
    }
    ticket.calculatePrice();
  }

  private void doPayNow(java.awt.event.ActionEvent evt) {

    try {
      updateModel();
      OrderController.saveOrder(ticket);

      ticket.clearDeletedItems();
      OrderController.saveOrder(ticket);

      if (isCheckMandatoryModifiers() && isTicketConstraintsOk()) {

        if (ticket.needsKitchenPrint()) {
          PosPrintService.printToKitchen(ticket);
        }

        OrderController.saveOrder(ticket);
        firePayOrderSelected();

      } else {

        POSMessageDialog.showError(errorMessage);
        errorMessage = "Problemas com o Pedido:";

      }

    } catch (PosException x) {
      POSMessageDialog.showError(x.getMessage());
    } catch (Exception e) {
      POSMessageDialog.showError(Application.getPosWindow(), POSConstants.ERROR_MESSAGE, e);
    }

  }

  private void doDeleteSelection(java.awt.event.ActionEvent evt) {
    Object object = ticketViewerTable.deleteSelectedItem();
    if (object != null) {
      updateView();
      if (object instanceof TicketItemModifier) {
        TicketItemModifier ticketItemModifier = (TicketItemModifier) object;
        String key = ticketItemModifier.getItemId() + "_" + ticketItemModifier.getGroupId();
        ModifierView modifierView = OrderView.getInstance().getModifierView();
        if (modifierView.isVisible()) {
          modifierView.updateVisualRepresentation(key);
        }
      }
    }
  }

  private void doIncreaseAmount(java.awt.event.ActionEvent evt) {

    if (ticketViewerTable.increaseItemAmount()) {
      ModifierView modifierView = OrderView.getInstance().getModifierView();
      if (modifierView.isVisible()) {
        modifierView.updateVisualRepresentation();
      }
      updateView();
    }

  }

  private void doDecreaseAmount(java.awt.event.ActionEvent evt) {
    if (ticketViewerTable.decreaseItemAmount()) {
      ModifierView modifierView = OrderView.getInstance().getModifierView();
      if (modifierView.isVisible()) {
        modifierView.updateVisualRepresentation();
      }
      updateView();
    }
  }

  private void doScrollDown(java.awt.event.ActionEvent evt) {
    ticketViewerTable.scrollDown();
  }

  private void doScrollUp(java.awt.event.ActionEvent evt) {
    ticketViewerTable.scrollUp();
  }

  private void doShowUpdatedTime() {
    Object selectedObject = ticketViewerTable.getSelected();

    if (selectedObject == null) {
      return;
    }

    if (selectedObject instanceof TicketItem) {
      TicketItem selectedItem = (TicketItem) selectedObject;

      if (selectedItem.getUpdateTime() != null) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
        POSMessageDialog.showMessage("Última modificação: " + dateFormat.format(selectedItem.getUpdateTime()) + ".");
      } else {
        POSMessageDialog.showMessage("Data de modificação não foi registrada.");
      }
    }
  }

  private void doSetUnitPrice() {
    Object selectedObject = ticketViewerTable.getSelected();

    if (selectedObject == null) {
      return;
    }

    if (selectedObject instanceof TicketItem) {
      TicketItem selectedItem = (TicketItem) selectedObject;

      MenuItemDAO dao = new MenuItemDAO();
      MenuItem menuItem = dao.get(selectedItem.getItemId());

      if (!menuItem.isBuffet()) {
        NumberSelectionDialog2 dialog = new NumberSelectionDialog2();
        dialog.setTitle("Preço");
        dialog.pack();
        dialog.setFloatingPoint(true);
        dialog.open();

        if (dialog.isCanceled()) {
          return;
        }
        
        double amount = dialog.getValue();

        if (amount != 0) {
          selectedItem.setUnitPrice(amount);
          updateAllView();
        }
      } else {
        NumberSelectionDialog2 dialog = new NumberSelectionDialog2();
        dialog.setTitle("Peso");
        dialog.pack();
        dialog.setFloatingPoint(true);
        dialog.open();

        if (dialog.isCanceled()) {
          return;
        }

        double weight = dialog.getValue();
        double unitPrice = menuItem.getPrice();

        double amount = weight * unitPrice;

        if (weight != 0) {
          selectedItem.setUnitPrice(amount);
          updateAllView();
        }        
      }
    }
  }

  private com.floreantpos.swing.TransparentPanel bottomPanel;
  private com.floreantpos.swing.PosButton btnCancel;
  private com.floreantpos.swing.PosButton btnDecreaseAmount;
  private com.floreantpos.swing.PosButton btnDelete;
  private com.floreantpos.swing.PosButton btnFinish;
  private com.floreantpos.swing.PosButton btnIncreaseAmount;
  private com.floreantpos.swing.PosButton btnPay;
  private com.floreantpos.swing.PosButton btnScrollDown;
  private com.floreantpos.swing.PosButton btnScrollUp;
  private javax.swing.JLabel jLabel1;
  private javax.swing.JLabel jLabel2;
  private javax.swing.JLabel jLabel5;
  private javax.swing.JLabel jLabel6;
  private com.floreantpos.swing.TransparentPanel jPanel1;
  private com.floreantpos.swing.TransparentPanel jPanel2;
  private com.floreantpos.swing.TransparentPanel jPanel3;
  private com.floreantpos.swing.TransparentPanel jPanel5;
  private javax.swing.JScrollPane jScrollPane1;
  private javax.swing.JSeparator jSeparator1;
  private javax.swing.JSeparator jSeparator2;
  private javax.swing.JSeparator jSeparator3;
  private javax.swing.JTextField tfDiscount;
  private javax.swing.JTextField tfSubtotal;
  private javax.swing.JTextField tfTax;
  private javax.swing.JTextField tfTotal;
  private com.floreantpos.ui.ticket.TicketViewerTable ticketViewerTable;

  public Ticket getTicket() {
    return ticket;
  }

  public void setTicket(Ticket _ticket) {
    this.ticket = _ticket;

    ticketViewerTable.setTicket(_ticket);

    updateView();
  }

  public void addTicketItem(TicketItem ticketItem) {
    ticketViewerTable.addTicketItem(ticketItem);
    updateView();
  }

  public void removeModifier(TicketItem parent, TicketItemModifier modifier) {
    ticketViewerTable.removeModifier(parent, modifier);
  }

  public void updateAllView() {
    ticketViewerTable.updateView();
    updateView();
  }

  public void selectRow(int rowIndex) {
    ticketViewerTable.selectRow(rowIndex);
  }

  public void updateView() {
    Integer ecfStatus = Application.getECFStatus();
    Boolean isTestSystem = Application.isTestSystem();
    
    User user = Application.getCurrentUser();
    UserType userType = user.getNewUserType();
    if (userType != null) {
      Set<UserPermission> permissions = userType.getPermissions();
      if (permissions != null) {
        btnPay.setEnabled(false);
      }
      for (UserPermission permission : permissions) {
        if (permission.equals(UserPermission.SETTLE_TICKET) && (ecfStatus == 2 || isTestSystem)) {
          btnPay.setEnabled(true);
        }
      }
    }
    
    if (ticket == null || ticket.getTicketItems() == null || ticket.getTicketItems().size() <= 0) {
      tfSubtotal.setText("");
      tfDiscount.setText("");
      tfTax.setText("");
      tfTotal.setText("");

      return;
    }

    ticket.calculatePrice();

    tfSubtotal.setText(numberFormat.format(ticket.getSubtotalAmount()));
    tfDiscount.setText(numberFormat.format(ticket.getDiscountAmount()));

    tfTax.setText(numberFormat.format(ticket.getGratuityAmount()));

    tfTotal.setText(numberFormat.format(ticket.getTotalAmount()));

  }

  public void addOrderListener(OrderListener listener) {
    orderListeners.add(listener);
  }

  public void removeOrderListener(OrderListener listener) {
    orderListeners.remove(listener);
  }

  public void firePayOrderSelected() {
    for (OrderListener listener : orderListeners) {
      listener.payOrderSelected(getTicket());
    }
  }

  public void setControlsVisible(boolean visible) {
    if (visible) {
      bottomPanel.setVisible(true);
      btnIncreaseAmount.setEnabled(true);
      btnDecreaseAmount.setEnabled(true);
      btnDelete.setEnabled(true);
    } else {
      bottomPanel.setVisible(false);
      btnIncreaseAmount.setEnabled(false);
      btnDecreaseAmount.setEnabled(false);
      btnDelete.setEnabled(false);
    }
  }

  private void updateSelectionView() {
    Object selectedObject = ticketViewerTable.getSelected();

    OrderView orderView = OrderView.getInstance();

    TicketItem selectedItem = null;
    if (selectedObject instanceof TicketItem) {
      selectedItem = (TicketItem) selectedObject;
      MenuItemDAO dao = new MenuItemDAO();
      MenuItem menuItem = dao.get(selectedItem.getItemId());
      MenuGroup menuGroup = menuItem.getParent();
      MenuItemView itemView = OrderView.getInstance().getItemView();
      if (!menuGroup.equals(itemView.getMenuGroup())) {
        itemView.setMenuGroup(menuGroup);
      }
      orderView.showView(MenuItemView.VIEW_NAME);

      MenuCategory menuCategory = menuGroup.getParent();
      orderView.getCategoryView().setSelectedCategory(menuCategory);
      return;
    } else if (selectedObject instanceof TicketItemModifier) {
      selectedItem = ((TicketItemModifier) selectedObject).getParent().getParent();
    }
    if (selectedItem == null) {
      return;
    }

    ModifierView modifierView = orderView.getModifierView();

    if (selectedItem.isHasModifiers()) {
      MenuItemDAO dao = new MenuItemDAO();
      MenuItem menuItem = dao.get(selectedItem.getItemId());
      if (!menuItem.equals(modifierView.getMenuItem())) {
        menuItem = dao.initialize(menuItem);
        modifierView.setMenuItem(menuItem, selectedItem);
      }

      MenuCategory menuCategory = menuItem.getParent().getParent();
      orderView.getCategoryView().setSelectedCategory(menuCategory);

      orderView.showView(ModifierView.VIEW_NAME);
    }
  }
  
  private Boolean isTicketConstraintsOk() {
    
    boolean retVal = true;
    
    if (!Application.isTestSystem() && ticket.getTotalAmount() <= 0) {
      errorMessage = errorMessage + "\n\nNão é possível criar pedidos com valor inferior a R$ 0,01.";
      retVal = false;      
    }
    
    if (ticket.getTicketItems().size() > 100) {
      errorMessage = errorMessage + "\n\nNão é possível criar pedidos com mais de 100 items.";
      retVal = false;
    }
    
    boolean hasDiscount = ticket.getDiscountAmount() > 0;
    
    int serviceItems = 0;
    int items = 0;
    int itemsWithoutPrice = 0;
    
    List<TicketItem> ticketItems = ticket.getTicketItems();
    for (TicketItem ticketItem : ticketItems) {
      
      if (ticketItem.isServiceItem()) {
        serviceItems++;
      } else {
        items++;
      }
      
      if (!Application.isTestSystem() && ticketItem.getSubtotalAmount() <= 0) {
        itemsWithoutPrice++;
      }
    }
    
    if (itemsWithoutPrice > 0) {
      errorMessage = errorMessage + "\n\nNão é possível criar pedidos que contenham itens com valor inferior a R$ 0,01.";
      retVal = false;      
    }
    
    if (hasDiscount && serviceItems > 1 && items > 0) {
      errorMessage = errorMessage + "\n\n- Não são permitidos pedidos com desconto que contenham produtos e seviços.";
      retVal = false;
    }
    
    if (hasDiscount && serviceItems > 1) {
      errorMessage = errorMessage + "\n\n- Não são permitidos pedidos com desconto que contenham mais de um serviço.";
      retVal = false;
    }
    
    if (serviceItems > 10) {
      errorMessage = errorMessage + "\n\n- Não são permitidos pedidos com mais de 10 serviços.";
      retVal = false;
    }
    
    return retVal;
  }

  private Boolean isCheckMandatoryModifiers() {
    Boolean isCheckMandatoryModifiers = true;
    List<TicketItem> ticketItems = ticket.getTicketItems();
    if (!ticketItems.isEmpty()) {
      for (TicketItem ticketItem : ticketItems) {
        List<TicketItemModifierGroup> modifierGroups = ticketItem.getTicketItemModifierGroups();
        if (modifierGroups != null && !modifierGroups.isEmpty()) {
          for (TicketItemModifierGroup modifierGroup : modifierGroups) {
            List<TicketItemModifier> modifiers = modifierGroup.getTicketItemModifiers();
            if (modifierGroup.getMinQuantity() > 0) {
              if (!modifiers.isEmpty()) {
                for (TicketItemModifier modifier : modifiers) {
                  if (modifier.getItemCount() < modifier.getMinQuantity()) {
                    isCheckMandatoryModifiers = false;
                  } else if (modifier.isPizzaModifier() && modifierGroup.countItems(true) > modifierGroup.getMaxQuantity()) {
                    isCheckMandatoryModifiers = false;
                  } else {
                    isCheckMandatoryModifiers = true;
                  }
                }
              } else if (ticketItem.isModifierMandatory()) {
                isCheckMandatoryModifiers = false;
              }
            } else if (ticketItem.isModifierMandatory()) {
              isCheckMandatoryModifiers = false;
            }
          }
        } else if (ticketItem.isModifierMandatory()) {
          isCheckMandatoryModifiers = false;
        }
      }
    }
    if (!isCheckMandatoryModifiers) {
      errorMessage = errorMessage + "\n\n- Existem Itens sem Modificações Obrigatórias ou com mais Modificações do que o permitido.\nObs.: Verifique os itens marcados com a cor Laranja.";
    }
    return isCheckMandatoryModifiers;
  }
}
